/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package proy1sistdistribuidos.modelo;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.util.Random;
import javax.crypto.SecretKey;
import proy1sistdistribuidos.modelo.seguridad.EncriptadorDesencriptador;
import proy1sistdistribuidos.modelo.seguridad.EncriptadorDesencriptadorDES;
import proy1sistdistribuidos.modelo.seguridad.InformacionSocketDF;
import proy1sistdistribuidos.modelo.seguridad.IntercambiadorLlaves;
import proy1sistdistribuidos.modelo.seguridad.IntercambiadorLlavesDF;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 *
 * @author Carlos Diaz Maya, Juan Felipe Garcia
 */
public class ProtocoloServidorSocketEstados {

    private static final int INICIAL = 0;
    private static final int CONSULTASOLICITARPERMISORECIBIDA = 1;
    private static final int RECIBIRESTADOGLOBAL = 2;
    private static final int ENVIARACUERDOLLAVES = 3;
    private static final int SOLICLLAVE = 4;
    private static final int FINAL = 5;
    private int estado = INICIAL;

    public String procesarEntrada(String comandoEntrada) throws Exception {
        String salida = null;
        if (estado == INICIAL) {

            if (comandoEntrada != null && comandoEntrada.length() > 1) {
                if (comandoEntrada.equals("SolicitarPermiso")) {
                    estado = CONSULTASOLICITARPERMISORECIBIDA;
                } else if (comandoEntrada.startsWith("RecibirEstadoGlobal_")) {
                    estado = RECIBIRESTADOGLOBAL;
                } else if (comandoEntrada.startsWith("EnviarAcuerdo_")) {
                    estado = ENVIARACUERDOLLAVES;
                } else if (comandoEntrada.startsWith("SolicLlave_")) {
                    estado = SOLICLLAVE;
                }
                  else {
                    salida = "";
                    estado = FINAL;
                }
            } else {
                salida = "";
                estado = FINAL;
            }
        }

        if (estado == CONSULTASOLICITARPERMISORECIBIDA) {
            String estadoLocal = ControladorEstado.obtenerInstancia().getEstadoLocal();
            if (estadoLocal != null && estadoLocal.equals(ControladorEstado.ESTADOABIERTO)) {
                salida = "true";
            } else if (estadoLocal != null && estadoLocal.equals(ControladorEstado.ESTADOCERRADO)) {
                salida = "false";
            } else {
                salida = null;
            }
            EstadoGeneral estadoGeneral = ControladorEstado.obtenerInstancia().getEstadoLocalDescarga();
            estadoGeneral.setNombreEstado(estadoGeneral.ENVIAR_RESPUESTA_SOLICITUD_PERMISO);
            estadoGeneral.setMensaje(salida);
            ControladorEstado.obtenerInstancia().actualizarEstadoGeneralInicial(estadoGeneral);

            estado = FINAL;
        }

        if (estado == RECIBIRESTADOGLOBAL) {
            String aux = "RecibirEstadoGlobal_";
            String estadoGlobalRecibidoBase64 = null;
            String comm = comandoEntrada.substring(aux.length());
            comm=comm.replaceAll("_CHARRO2_", "\r\n");
            comm=comm.replaceAll("_CHARRO_", "\n");
            estadoGlobalRecibidoBase64 = comm;

            BASE64Decoder descodifBase64 = new BASE64Decoder();
            byte[] cadenaXMLBytes = descodifBase64.decodeBuffer(estadoGlobalRecibidoBase64);
            String cadenaXML = new String(cadenaXMLBytes);
            EstructuraDatosEstado estructuraEstado = new EstructuraDatosEstado(cadenaXML);
            estructuraEstado.getEstadoGeneralInicial();

            ControladorEstado.obtenerInstancia().getEstadoGlobalDescarga().put(estructuraEstado.getEstadoGeneralInicial().getIdentificadorFuente(), estructuraEstado.getEstadoGeneralInicial());
            EstructuraDatosEstado estructuraEstadoLocal = new EstructuraDatosEstado(ControladorEstado.obtenerInstancia().getEstadoLocalDescarga(), ControladorEstado.obtenerInstancia().getEstadoGlobalDescarga() );
            String estructuraEstadoLocalXML = estructuraEstadoLocal.aString();
            estructuraEstadoLocal.persistirEstructura(ControladorEstado.RUTAFISICA);


            byte[] estructuraEstadoLocalXMLBytes = estructuraEstadoLocalXML.getBytes();
            BASE64Encoder encodifBase64 = new BASE64Encoder();
            salida = encodifBase64.encode(estructuraEstadoLocalXMLBytes);
            salida = salida.replaceAll("\r\n","_CHARRO2_");
            salida = salida.replaceAll("\n","_CHARRO_");
            estado = FINAL;
        }

        if(estado == ENVIARACUERDOLLAVES){
            String aux = "EnviarAcuerdo_";
            String llavePublicaRecibidaBase64 = null;
            String comm = comandoEntrada.substring(aux.length());
            comm=comm.replaceAll("_CHARRO2_", "\r\n");
            comm=comm.replaceAll("_CHARRO_", "\n");
            llavePublicaRecibidaBase64 = comm;
            BASE64Decoder descodifBase64 = new BASE64Decoder();
            byte[] cadenaXMLBytes = descodifBase64.decodeBuffer(llavePublicaRecibidaBase64);
            String cadenaXML = new String(cadenaXMLBytes);
            InformacionSocketDF llavePublicaRecibida = new InformacionSocketDF(cadenaXML);
            IntercambiadorLlaves intercambiador = IntercambiadorLlavesDF.obtenerSolitario();
            InformacionSocketDF infointerc = intercambiador.recibirIntercambioLlaves(llavePublicaRecibida);
            String infointercXML = infointerc.aXMLString();

            byte[] infointercXMLBytes = infointercXML.getBytes();
            BASE64Encoder encodifBase64 = new BASE64Encoder();
            salida = encodifBase64.encode(infointercXMLBytes);
            salida = salida.replaceAll("\r\n","_CHARRO2_");
            salida = salida.replaceAll("\n","_CHARRO_");
            estado = FINAL;
        }

        if(estado == SOLICLLAVE) {
            String aux = "SolicLlave_";
            String idSesionRecibido = comandoEntrada.substring(aux.length());

             //Enviar llave AES propia usando la llave de encripcion del acuerdo Diffie Hellman
             IntercambiadorLlaves interc = IntercambiadorLlavesDF.obtenerSolitario();

             SecretKey llaveBlowfish = interc.obtenerLlaveEncripcionDesencripcionAcordada(idSesionRecibido);
             EncriptadorDesencriptador encdescIntercambio = EncriptadorDesencriptadorDES.obtenerSolitario();

             //Se obtiene la llave AES utilizada
             SecretKey llaveAES = AdministradorJXTA.obtenerLlaveAES();

             XStream elStream = new XStream(new DomDriver());
             elStream.alias("FriendlyInfo", SecretKey.class);
             String llaveAESXML = elStream.toXML(llaveAES);

             String llaveEncriptada = encdescIntercambio.encriptarMensaje(llaveAESXML, llaveBlowfish);

             salida = llaveEncriptada;
        }

        if (estado == FINAL) {
            estado = INICIAL;
        }
        return salida;
    }
}